typedef struct {
    int* a;
    int front;
    int rear;
    int k;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->rear == obj->front;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear + 1) % (obj->k + 1) == obj->front;
}


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if (obj == NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    obj->front = 0;
    obj->rear = 0;
    obj->k = k;
    int* s = (int*)malloc(sizeof(int) * (k + 1));
    obj->a = s;
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }
    obj->a[obj->rear] = value;
    obj->rear++;
    obj->rear %= (obj->k + 1);
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    assert(obj);
    if (myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    obj->front++;
    obj->front %= (obj->k + 1);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    assert(obj);
    if (!myCircularQueueIsEmpty(obj))
        return obj->a[obj->front];
    else
        return -1;
}

int myCircularQueueRear(MyCircularQueue* obj) {
    assert(obj);
    if (!myCircularQueueIsEmpty(obj))
        return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
    else
        return -1;
}


void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    obj->front = 0;
    obj->rear = 0;
    obj->k = 0;
    free(obj);
}



typedef int STDataType;

typedef struct Stack
{
    STDataType* a;
    int top;
    int capacity;
}ST;

void STInit(ST* head);
void STDestroy(ST* head);
void STPush(ST* head, STDataType x);
void STPop(ST* head);
STDataType STTop(ST* head);
bool STEmpty(ST* head);
int STSize(ST* head);

bool STEmpty(ST* head)
{
    return head->top == 0;
}

void STInit(ST* head)
{
    STDataType* pf = (STDataType*)malloc(sizeof(STDataType) * 5);
    if (pf == NULL)
    {
        perror("malloc fail");
        return;
    }
    head->a = pf;
    head->top = 0;
    head->capacity = 5;
}

void STDestroy(ST* head)
{
    assert(head);
    free(head->a);
    head->a = NULL;
    head->capacity = 0;
    head->top = 0;
}

void STPush(ST* head, STDataType x)
{
    if (head->top == head->capacity)
    {
        STDataType* newnode = (STDataType*)realloc(head->a, sizeof(STDataType) * (head->capacity) * 2);
        if (newnode == NULL)
        {
            perror("realloc fail");
            return;
        }
        head->a = newnode;
        head->capacity *= 2;
    }
    head->a[head->top] = x;
    head->top++;
}

void STPop(ST* head)
{
    assert(head);
    assert(!STEmpty(head));
    head->top--;
}

STDataType STTop(ST* head)
{
    assert(head);
    assert(!STEmpty(head));
    return head->a[head->top - 1];
}


int STSize(ST* head)
{
    return head->top;
}

////////////////////////////////////////////////////////////////////////////////////////////

typedef struct {
    ST pushStack;
    ST popStack;
} MyQueue;


bool myQueueEmpty(MyQueue* obj) {
    return STSize(&obj->pushStack) == 0 && STSize(&obj->popStack) == 0;
}


MyQueue* myQueueCreate() {
    MyQueue* obj;
    MyQueue* s = (MyQueue*)malloc(sizeof(MyQueue));
    if (s == NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    obj = s;
    STInit(&obj->pushStack);
    STInit(&obj->popStack);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    STPush(&obj->pushStack, x);
}

int myQueuePop(MyQueue* obj) {
    assert(obj);
    assert(!myQueueEmpty(obj));
    if (STEmpty(&obj->popStack))
    {
        while (!STEmpty(&obj->pushStack))
        {
            STPush(&obj->popStack, STTop(&obj->pushStack));
            STPop(&obj->pushStack);
        }
    }
    int ret = STTop(&obj->popStack);
    STPop(&obj->popStack);
    return ret;
}

int myQueuePeek(MyQueue* obj) {
    assert(obj);
    assert(!myQueueEmpty(obj));
    if (STEmpty(&obj->popStack))
    {
        while (!STEmpty(&obj->pushStack))
        {
            STPush(&obj->popStack, STTop(&obj->pushStack));
            STPop(&obj->pushStack);
        }
    }
    return STTop(&obj->popStack);

}


void myQueueFree(MyQueue* obj) {
    STDestroy(&obj->pushStack);
    STDestroy(&obj->pushStack);
    free(obj);
}